#!/usr/bin/python3
"""
Configure cloud-init

The 'config' option allows to configure cloud-init by creating a
configuration file under `/etc/cloud/cloud.cfg.d` with the name
specified by `filename`.

Constrains:
  - Each configuration file definition must contain at least one configuration

Currently supported subset of cloud-init configuration:
  - 'system_info' section
    - 'default_user' section
      - 'name' option
"""


import sys
import yaml


import osbuild.api


SCHEMA = r"""
"definitions": {
  "reporting_handlers": {
    "type": "string",
    "enum": ["log", "print", "webhook", "hyperv"]
  }
},
"additionalProperties": false,
"required": ["config", "filename"],
"properties": {
  "filename": {
    "type": "string",
    "description": "Name of the cloud-init configuration file.",
    "pattern": "^[\\w.-]{1,251}\\.cfg$"
  },
  "config": {
    "additionalProperties": false,
    "type": "object",
    "description": "cloud-init configuration",
    "minProperties": 1,
    "properties": {
      "system_info": {
        "additionalProperties": false,
        "type": "object",
        "description": "'system_info' configuration section.",
        "minProperties": 1,
        "properties": {
          "default_user": {
            "additionalProperties": false,
            "type": "object",
            "description": "Configuration of the 'default' user created by cloud-init.",
            "minProperties": 1,
            "properties": {
              "name": {
                "type": "string",
                "description": "username of the 'default' user."
              }
            }
          }
        }
      },
      "reporting": {
        "type": "object",
        "additionalProperties": false,
        "description": "Define reporting endpoints.",
        "minProperties": 1,
        "properties": {
          "logging": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "type": {
                "$ref": "#/definitions/reporting_handlers"
              }
            }
          },
          "telemetry": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "type": {
                "$ref": "#/definitions/reporting_handlers"
              }
            }
          }
        }
      },
      "datasource_list": {
        "type": "array",
        "items": {
          "type": "string",
          "enum": ["Azure"]
        }
      },
      "datasource": {
        "type": "object",
        "description": "Sources of configuration data for cloud-init.",
        "minProperties": 1,
        "properties": {
          "Azure": {
            "type": "object",
            "minProperties": 1,
            "properties": {
              "apply_network_config": {
                "type": "boolean",
                "description": "Whether to use network configuration described by Azure’s IMDS endpoint",
                "default": true
              }
            }
          }
        }
      },
      "output": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "init": {
            "description": "Redirect the output of the init stage",
            "type": "string"
          },
          "config": {
            "description": "Redirect the output of the config stage",
            "type": "string"
          },
          "final": {
            "description": "Redirect the output of the final stage",
            "type": "string"
          },
          "all": {
            "description": "Redirect the output of all stages",
            "type": "string"
          }
        }
      }
    }
  }
}
"""


# Writes the passed `config` object as is into the configuration file in YAML format.
# The validity of the `config` content is assured by the SCHEMA.
def main(tree, options):
    filename = options.get("filename")
    config = options.get("config", {})

    config_files_dir = f"{tree}/etc/cloud/cloud.cfg.d"

    with open(f"{config_files_dir}/{filename}", "w") as f:
        yaml.dump(config, f, default_flow_style=False)

    return 0


if __name__ == '__main__':
    args = osbuild.api.arguments()
    r = main(args["tree"], args["options"])
    sys.exit(r)
